import { Injectable, Logger, Optional } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { DataSource } from 'typeorm';

@Injectable()
export class HealthCheckService {
  private readonly logger = new Logger(HealthCheckService.name);

  constructor(
    private readonly configService: ConfigService,
    @Optional() private readonly dataSource?: DataSource,
  ) {}

  /**
   * 检查所有外部服务连接状态
   * @returns Promise<boolean> 所有服务都连接成功返回true，否则返回false
   */
  async checkAllConnections(): Promise<boolean> {
    this.logger.log('🔍 开始检查所有外部服务连接状态...');
    
    const checks = [
      this.checkDatabaseConnection(),
      this.checkRedisConnection(),
    ];

    try {
      const results = await Promise.allSettled(checks);
      const allSuccess = results.every(result => result.status === 'fulfilled' && result.value);
      
      if (allSuccess) {
        this.logger.log('✅ 所有外部服务连接检查通过！');
      } else {
        this.logger.error('❌ 部分外部服务连接失败！');
        this.logFailedConnections(results);
      }
      
      return allSuccess;
    } catch (error) {
      this.logger.error('💥 连接检查过程中发生错误:', error);
      return false;
    }
  }

  /**
   * 检查数据库连接
   */
  async checkDatabaseConnection(): Promise<boolean> {
    try {
      this.logger.log('📊 检查数据库连接...');
      if (!this.dataSource) {
        this.logger.warn('⚠️ 未注入 DataSource，跳过数据库连接检查');
        return true;
      }
      
      if (!this.dataSource.isInitialized) {
        await this.dataSource.initialize();
      }
      
      // 执行简单查询测试连接
      await this.dataSource.query('SELECT 1');
      
      const dbHost = this.configService.get('ADMIN_DATABASE_HOST', 'localhost');
      const dbPort = this.configService.get('ADMIN_DATABASE_PORT', 3306);
      const dbName = this.configService.get('ADMIN_DATABASE_TABLE', 'kv_blog');
      const dbType = this.configService.get('DB_TYPE', 'mysql');
      
      this.logger.log(`✅ 数据库连接成功: ${dbType}://${dbHost}:${dbPort}/${dbName}`);
      return true;
    } catch (error) {
      const dbHost = this.configService.get('ADMIN_DATABASE_HOST', 'localhost');
      const dbPort = this.configService.get('ADMIN_DATABASE_PORT', 3306);
      const dbName = this.configService.get('ADMIN_DATABASE_TABLE', 'kv_blog');
      const dbType = this.configService.get('DB_TYPE', 'mysql');
      
      this.logger.error(`❌ 数据库连接失败: ${dbType}://${dbHost}:${dbPort}/${dbName}`);
      this.logger.error('数据库错误详情:', error.message);
      return false;
    }
  }

  /**
   * 检查Redis连接
   */
  async checkRedisConnection(): Promise<boolean> {
    try {
      this.logger.log('🔄 检查Redis连接...');
      
      // 如果没有 Redis 依赖，跳过检查
      try {
        const { Redis } = await import('ioredis');
        const redis = new Redis({
          host: this.configService.get('REDIS_HOST', 'localhost'),
          port: this.configService.get('REDIS_PORT', 6379),
          password: this.configService.get('REDIS_PASSWORD'),
          db: this.configService.get('REDIS_DB', 0),
          lazyConnect: true,
          connectTimeout: 5000,
          maxRetriesPerRequest: 3,
        });
        
        // 执行PING命令测试连接
        const pong = await redis.ping();
        
        if (pong === 'PONG') {
          const redisHost = this.configService.get('REDIS_HOST', 'localhost');
          const redisPort = this.configService.get('REDIS_PORT', 6379);
          const redisDb = this.configService.get('REDIS_DB', 0);
          
          this.logger.log(`✅ Redis连接成功: redis://${redisHost}:${redisPort}/${redisDb}`);
          await redis.quit();
          return true;
        } else {
          throw new Error(`Redis PING 响应异常: ${pong}`);
        }
      } catch (importError) {
        this.logger.warn('⚠️  Redis 模块未安装，跳过 Redis 连接检查');
        return true; // 如果没有安装 Redis，则跳过检查
      }
    } catch (error) {
      const redisHost = this.configService.get('REDIS_HOST', 'localhost');
      const redisPort = this.configService.get('REDIS_PORT', 6379);
      const redisDb = this.configService.get('REDIS_DB', 0);
      
      this.logger.error(`❌ Redis连接失败: redis://${redisHost}:${redisPort}/${redisDb}`);
      this.logger.error('Redis错误详情:', error.message);
      return false;
    }
  }

  /**
   * 记录失败的连接
   */
  private logFailedConnections(results: PromiseSettledResult<boolean>[]): void {
    results.forEach((result, index) => {
      if (result.status === 'rejected' || (result.status === 'fulfilled' && !result.value)) {
        const serviceName = index === 0 ? 'Database' : 'Redis';
        this.logger.error(`${serviceName} 连接检查失败`);
        if (result.status === 'rejected') {
          this.logger.error(`${serviceName} 错误:`, result.reason);
        }
      }
    });
  }

  /**
   * 获取所有服务的详细状态
   */
  async getDetailedHealthStatus() {
    const dbStatus = await this.checkDatabaseConnection();
    const redisStatus = await this.checkRedisConnection();
    
    return {
      database: {
        status: dbStatus ? 'connected' : 'disconnected',
        config: {
          type: this.configService.get('DB_TYPE', 'mysql'),
          host: this.configService.get('ADMIN_DATABASE_HOST', 'localhost'),
          port: this.configService.get('ADMIN_DATABASE_PORT', 3306),
          database: this.configService.get('ADMIN_DATABASE_TABLE', 'kv_blog'),
        },
      },
      redis: {
        status: redisStatus ? 'connected' : 'disconnected',
        config: {
          host: this.configService.get('REDIS_HOST', 'localhost'),
          port: this.configService.get('REDIS_PORT', 6379),
          db: this.configService.get('REDIS_DB', 0),
        },
      },
      overall: dbStatus && redisStatus ? 'healthy' : 'unhealthy'
    };
  }
}
